package com.mall.module.system.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mall.common.exception.BusinessException;
import com.mall.common.result.ResultCode;
import com.mall.common.util.UserContext;
import com.mall.module.system.domain.dto.RoleAuthDTO;
import com.mall.module.system.domain.dto.RoleCreateDTO;
import com.mall.module.system.domain.dto.RoleUpdateDTO;
import com.mall.module.system.domain.entity.SysRole;
import com.mall.module.system.domain.entity.SysRoleMenu;
import com.mall.module.system.domain.entity.SysRolePermission;
import com.mall.module.system.domain.entity.SysUser;
import com.mall.module.system.domain.vo.PermissionTreeVO;
import com.mall.module.system.mapper.*;
import com.mall.module.system.service.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 角色服务实现类
 */
@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;
    
    @Autowired
    private SysMenuMapper sysMenuMapper;
    
    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    
    /**
     * 获取用户角色标识集合
     *
     * @param userId 用户ID
     * @return 角色标识集合
     */
    @Override
    public Set<String> getRolesByUserId(Long userId) {
        List<SysRole> roleList = sysRoleMapper.selectRolesByUserId(userId);
        
        // 如果没有角色，返回空集合
        if (roleList == null || roleList.isEmpty()) {
            return new HashSet<>();
        }
        
        // 提取角色标识
        return roleList.stream()
                .map(SysRole::getName)
                .collect(Collectors.toSet());
    }

    @Override
    public PageInfo<SysRole> listRoles(int pageNum, int pageSize, String roleName, Integer status) {
        PageHelper.startPage(pageNum, pageSize);
        List<SysRole> list = sysRoleMapper.selectRoleList(roleName, status);
        return new PageInfo<>(list);
    }

    @Override
    public SysRole getRoleById(Long roleId) {
        return sysRoleMapper.selectRoleById(roleId);
    }

    @Override
    @Transactional
    public boolean createRole(RoleCreateDTO dto) {
        SysRole role = new SysRole();
        role.setName(dto.getName());
        role.setDescription(dto.getDescription());
        role.setStatus(dto.getStatus());
        //获取当前登录用户的ID
        Long currentId =  UserContext.getUserId();
        role.setCreatorId(currentId);
        role.setCreateTime(LocalDateTime.now());
        role.setIsDeleted(0);
        return sysRoleMapper.insertRole(role) > 0;
    }

    @Override
    @Transactional
    public boolean updateRole(Long roleId, RoleUpdateDTO dto) {
        SysRole role = sysRoleMapper.selectRoleById(roleId);
        if (role == null) return false;
        role.setName(dto.getName());
        role.setDescription(dto.getDescription());
        role.setStatus(dto.getStatus());
        role.setUpdaterId(1L); // TODO: 获取当前登录用户ID
        role.setUpdateTime(LocalDateTime.now());
        return sysRoleMapper.updateRole(role) > 0;
    }

    @Override
    @Transactional
    public boolean deleteRole(Long roleId) {
        return sysRoleMapper.deleteRoleById(roleId) > 0;
    }

    @Override
    @Transactional
    public boolean updateRoleStatus(Long roleId, Integer status) {
        return sysRoleMapper.updateRoleStatus(roleId, status) > 0;
    }

    @Override
    @Transactional
    public boolean assignRoleMenus(Long roleId, List<Long> menuIds) {
        sysRoleMapper.deleteRoleMenuByRoleId(roleId);
        if (menuIds != null && !menuIds.isEmpty()) {
            for (Long menuId : menuIds) {
                sysRoleMapper.insertRoleMenu(roleId, menuId);
            }
        }
        return true;
    }

    @Override
    @Transactional
    public boolean assignRolePermissions(Long roleId, List<Long> permissionIds) {
        sysRoleMapper.deleteRolePermissionByRoleId(roleId);
        if (permissionIds != null && !permissionIds.isEmpty()) {
            for (Long permissionId : permissionIds) {
                sysRoleMapper.insertRolePermission(roleId, permissionId);
            }
        }
        return true;
    }

    @Override
    public List<Long> getRoleMenuIds(Long roleId) {
        return sysRoleMapper.selectMenuIdsByRoleId(roleId);
    }

    @Override
    public List<Long> getRolePermissionIds(Long roleId) {
        return sysRoleMapper.selectPermissionIdsByRoleId(roleId);
    }

    @Override
    public List<SysUser> getRoleUsers(Long roleId) {
        return sysRoleMapper.selectUsersByRoleId(roleId);
    }

    @Override
    @Transactional
    public boolean assignUsersToRole(Long roleId, List<Long> userIds) {
        sysRoleMapper.deleteUserRoleByRoleId(roleId);
        if (userIds != null && !userIds.isEmpty()) {
            for (Long userId : userIds) {
                sysRoleMapper.insertUserRole(userId, roleId);
            }
        }
        return true;
    }

    @Override
    public PermissionTreeVO getRolePermissionTree(Long roleId) {
        // 获取角色已分配的菜单ID和权限ID
        List<Long> roleMenuIds = sysRoleMapper.selectMenuIdsByRoleId(roleId);
        List<Long> rolePermissionIds = sysRoleMapper.selectPermissionIdsByRoleId(roleId);
        
        // 构建权限树
        PermissionTreeVO treeVO = new PermissionTreeVO();
        
        // 1. 获取所有菜单并构建树结构
        List<Map<String, Object>> allMenus = sysMenuMapper.selectAllMenus();
        List<PermissionTreeVO.MenuTreeNode> menuTree = buildMenuTree(allMenus, 0L, roleMenuIds);
        treeVO.setMenuTree(menuTree);
        
        // 2. 获取所有权限并标记已分配的权限
        List<Map<String, Object>> allPermissions = sysPermissionMapper.selectAllPermissions();
        List<PermissionTreeVO.Permission> permissions = new ArrayList<>();
        
        for (Map<String, Object> map : allPermissions) {
            PermissionTreeVO.Permission permission = new PermissionTreeVO.Permission();
            permission.setId(((Number) map.get("id")).longValue());
            permission.setName((String) map.get("name"));
            permission.setPermissionKey((String) map.get("permission_key"));
            permissions.add(permission);
        }
        
        treeVO.setPermissions(permissions);
        
        return treeVO;
    }

    @Override
    public PermissionTreeVO getFullPermissionTree() {
        // 构建完整权限树
        PermissionTreeVO treeVO = new PermissionTreeVO();
        
        // 1. 获取所有菜单并构建树结构
        List<Map<String, Object>> allMenus = sysMenuMapper.selectAllMenus();
        List<PermissionTreeVO.MenuTreeNode> menuTree = buildMenuTree(allMenus, 0L, null);
        treeVO.setMenuTree(menuTree);
        // 2. 获取所有权限
        List<Map<String, Object>> allPermissions = sysPermissionMapper.selectAllPermissions();
        List<PermissionTreeVO.Permission> permissions = new ArrayList<>();
        
        for (Map<String, Object> map : allPermissions) {
            PermissionTreeVO.Permission permission = new PermissionTreeVO.Permission();
            permission.setId(((Number) map.get("id")).longValue());
            permission.setName((String) map.get("name"));
            permission.setPermissionKey((String) map.get("permission_key"));
            permissions.add(permission);
        }
        treeVO.setPermissions(permissions);
        return treeVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean assignRoleAuthorizations(Long roleId, RoleAuthDTO dto) {
        // 1. 校验角色是否存在
        SysRole role = sysRoleMapper.selectRoleById(roleId);
        if (role == null) {
            throw new BusinessException(ResultCode.ROLE_NOT_EXIST);
        }
        // 2. 校验管理员角色保护
        if (isAdminRole(role)) {
            throw new BusinessException(ResultCode.ROLE_PERMISSION_NOT_MODIFY);
        }
        // 3. 更新角色权限关系
        updateRolePermissions(roleId, dto.getPermissionIds());
        // 4. 更新角色菜单关系
        updateRoleMenus(roleId, dto.getMenuIds());

        return true;
    }

    private boolean isAdminRole(SysRole role) {
        return "admin".equals(role.getName()) || role.getId() == 1L;
    }

    private void updateRolePermissions(Long roleId, List<Long> permissionIds) {
        // 删除原有权限
        sysRolePermissionMapper.deleteByRoleId(roleId);
        // 插入新权限
        if (!CollectionUtils.isEmpty(permissionIds)) {
            List<SysRolePermission> relations = permissionIds.stream()
                .map(pid -> new SysRolePermission(roleId, pid))
                .collect(Collectors.toList());
            sysRolePermissionMapper.batchInsert(relations);
        }
    }

    private void updateRoleMenus(Long roleId, List<Long> menuIds) {
        // 删除原有菜单
        sysRoleMenuMapper.deleteByRoleId(roleId);

        // 插入新菜单
        if (!CollectionUtils.isEmpty(menuIds)) {
            List<SysRoleMenu> relations = menuIds.stream()
                .map(mid -> new SysRoleMenu(roleId, mid))
                .collect(Collectors.toList());
            sysRoleMenuMapper.batchInsert(relations);
        }
    }


    /**
     * 递归构建菜单树
     * 
     * @param allMenus 所有菜单列表
     * @param parentId 父菜单ID
     * @param roleMenuIds 角色已分配的菜单ID列表，用于标记
     * @return 菜单树节点列表
     */
    private List<PermissionTreeVO.MenuTreeNode> buildMenuTree(List<Map<String, Object>> allMenus, Long parentId, List<Long> roleMenuIds) {
        List<PermissionTreeVO.MenuTreeNode> children = new ArrayList<>();
        
        for (Map<String, Object> menu : allMenus) {
            Long id = ((Number) menu.get("id")).longValue();
            Long menuParentId = ((Number) menu.get("parent_id")).longValue();
            
            if (parentId.equals(menuParentId)) {
                PermissionTreeVO.MenuTreeNode node = new PermissionTreeVO.MenuTreeNode();
                node.setId(id);
                node.setName((String) menu.get("name"));
                
                // 递归构建子菜单
                node.setChildren(buildMenuTree(allMenus, id, roleMenuIds));
                
                children.add(node);
            }
        }
        
        return children;
    }
} 